Skip to content

feat: add developer-gated Prompt Shortcuts [risk:high] - #575

Merged
Leeeon233 merged 25 commits into
mainfrom
feat/prompt-shortcut-settings-sync
Sep 11, 2026
Merged

feat: add developer-gated Prompt Shortcuts [risk:high]#575
Leeeon233 merged 25 commits into
mainfrom
feat/prompt-shortcut-settings-sync

Conversation

@Leeeon233

@Leeeon233 Leeeon233 commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Risk: 🔴 high | Confidence: medium — private/shared persistence remains; real gateway validation is incomplete.

Prompt Shortcuts save scoped private or workspace-shared Prompts, default off behind Developer mode and the Beta switch. Selecting one from / loads and rechecks its body, then replaces the query with ordinary editable text and ordinary mention ranges. Selection cancellation preserves newer input.

There is no Shortcut chip, invocation snapshot, dedicated composer draft store, custom Undo history or Shortcut send compiler. Ordinary composer persistence and send expansion own the inserted content. Settings reuse composer mentions and exclude recursive Shortcuts, nested ACP commands and session references.

All PR-added tests, Storybook and repository documentation remain removed. Validation used temporary tests (not committed): plain insertion and offsets, cancellation, version changes and React integration, plus 68 existing mention/submission tests. Full workspace typecheck, targeted lint (no errors), formatting and i18n passed.

Limits: actual dependency resolution, full sync conflict repair, cache eviction and real gateway E2E remain incomplete. The outer check:affected wrapper still fails on the existing indexed OSS revision mismatch. Old dedicated invocation checkpoints are no longer restored; this change does not delete their local database. No parent gitlink change is committed.

Leeeon233 and others added 13 commits September 5, 2026 12:41
Add scoped private/shared shortcut catalogs, lazy LoroDoc bodies, durable local publication recovery, settings authoring and Storybook prototypes. Slash invocation and composer send integration remain follow-up work.

Model: gpt-6-astra
…sk:high]

Settings now reads as the same surface as Agent Roles and MCP: one dialog
header/scroll/footer editor built from the shared `form-primitives` grammar,
Radix selects for the three scope axes, a Switch for sharing with its
visibility warning, and the shared catalog row. Adds scope pills, per-row
publication state, a read-only view for another member's shared Shortcut, and
disabled mention kinds that name the scope axes they still need.

Also carries this branch's local-first storage work: a separate local ledger,
write intents and immutable publication jobs, so a pending publication stays
durable without ever blocking Save or Delete.

Slash invocation, the variable argument tray and composer send integration
remain follow-up work.

Model: claude-opus-5
Scope moves out of its own section and sits inline above the prompt input,
each axis naming itself in its trigger, with the explanation folded into the
prompt hint. The description field says what it is and where it shows, a
variable's default sits beside its name instead of under it, and the prompt
box starts shorter.

Model: claude-opus-5
A default value is usually a few words, so the field starts at a single row
and tracks its content instead of reserving two. `AutoGrowTextarea` joins the
shared settings primitives, and re-measures on width changes because wrapping
is what decides the row count.

Model: claude-opus-5
Add independent Slash discovery, cancellable snapshot selection, inline invocation parameters, isolated draft recovery, and ordered prompt compilation with expand-and-edit support.

Model: gpt-6
Reuse the shared composer mention portal within the nearest modal and constrain desktop and mobile positioning to its bounds. Cover real Shortcut creation dialogs in Storybook and modal selection in regression tests.

Model: gpt-6
…sk:medium]

The tray now reads as the settings variable editor it mirrors: the `!{name}`
token beside its value, growing from one row, a missing value tinting its own
token instead of adding an asterisk. Desktop keeps a section header with the
dismiss action; mobile keeps the sheet with a full-width Done.

"Expand and edit" is removed. It existed to change a template's body, which
Settings already does — durably, for every invocation — and it paid for that
with a whole draft vocabulary of its own: generated unresolved markers, literal
ranges that stop substituted text being rescanned, their persistence and undo
rules, and an extra send-time check for leftover markers. A chip is atomic
again, so all of that goes with it.

Model: claude-opus-5
The catalog row was four left-aligned lines against an empty right half. It is
now two: identity reads down the left, and what the author set — scope, variable
count — plus what is happening to it sit against the right edge. Both halves
wrap rather than switching on a viewport breakpoint, because settings render in
a panel far narrower than the window. Status copy shortens to phrases that fit
that column.

The tray drops the "fill these variables" line between the prompt and the
fields and sits against the invocation instead. The chip's own badge and the
tinted token already name what is missing; a third sentence only pushed the
fields away from the thing they belong to.

Model: claude-opus-5
A Shortcut carries an optional `emoji`, normalized on the way in and projected
into the index so the list can show it without loading a body. It replaces the
`/` glyph in the catalog tile; unset renders the default rather than an empty
slot. The emoji control itself moves out of the Agent Role editor into
`settings/emoji-field.tsx`, so the two editors cannot grow two of them.

Also drops the `!N` badge painted over an invocation chip — the chip already
turns red and the tray names the values — and with it the mention primitive's
`badge` slot, which had no other caller.

While a parameter tray is open the composer stops reserving its blank writing
rows: those rows are room for writing, and reserving them above the tray left a
band of empty box between the `/command` and the fields it belongs to.

Model: claude-opus-5
…k:medium]

Four things the composer and the catalog were getting wrong:

Clearing the prompt to empty dropped focus. The reset remounts the mention tree
to re-arm the hydrators, which replaces the textarea node; restoring focus was
conditional on the caller having passed a ref, and the settings template editor
passes none. The component keeps its own ref now and hands the node to the
forwarded one as well.

The catalog reported background publication. A local save is already durable and
the runtime retries on its own, so neither state is something a reader can act on
from a row. The only status left is the one its author must repair: a reference
that no longer fits the saved scope.

The `/` menu shows each Shortcut's own emoji, the way an Agent Role's row does.

A chip now carries the values that were filled into it (`shortcutChipText`,
applied on tray close), capped by code points so a truncation cannot split a
surrogate pair. A draft of three identical `/review` chips was not something
anyone could check before sending. Both forms of the text stay valid, so a draft
stored before its values still restores.

Model: claude-opus-5
A Shortcut is a Prompt and a scope now, nothing else. `!{name}` is ordinary
text: stored, expanded and sent exactly as written.

Gone from the model: the `variables` field, its schema and byte limits, the
index's `variableCount`, placeholder parsing and escaping, value injection, the
`missing_variables` error code, and `updateShortcutInvocation` (which existed
only to migrate values across a reload). `ShortcutInvocation` is `{ id,
snapshot }`, so `expandShortcut` is a straight lowering of the snapshot's text
and mentions.

Gone from the UI: the Settings variables section, the composer's parameter tray
and bottom sheet, their send gate, the chip's missing-count colouring, and the
value label a chip carried. What remains of the composer bridge is
`shortcut-invocation-status.tsx` — why an inserted chip cannot be sent, which is
about live context rather than anything the caller types.

The invocation schema is deliberately not strict: a draft stored while values
existed still restores, minus the ignored key.

Model: claude-opus-5
Default the opt-in off and share the developer-mode gate across settings navigation, direct panel access, mention selection and the workspace runtime. Preserve saved data and cover toggle transitions and late selection results.

Model: gpt-6
Clear the Shortcut checkpoint before successful landing navigation, fenced by composer mount and draft identity so late session acceptance cannot delete or navigate a replacement draft. Add deterministic recovery regressions and satisfy the branch formatting gate.

Model: gpt-6
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-10T06:00:26.392316Z 665a216 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Preserve composer submission ownership and Shortcut preparation while integrating main. Clear retired accepted Shortcut checkpoints only when their submitted version remains current.

Model: gpt-6

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 362a08f32b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +375 to +379
await this.put({
entry,
published: current?.operation ? current.published : entry,
operation: 'delete',
deleted: true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Revoke the published body on delete

When an author deletes a successfully published Shortcut from the authoring device, entry is the local working projection, while preparePublication() uploaded a fresh body and stored that distinct projection in current.published. Persisting the caller's working entry here therefore makes publishRecord() call revokeShortcut with a bodyDocId that was never activated; a host enforcing the request's body/visibility fence cannot revoke it, so a shared Shortcut remains accessible and every retry repeats the wrong request. Enqueue the published projection for remote deletion while retaining the local deletion state.

AGENTS.md reference: packages/shared/src/prompt-shortcuts/AGENTS.md:L22-L25

Useful? React with 👍 / 👎.

await this.recover();
const existing = this.publication(id);
const current = this.get(id);
if (existing && !current?.deleted) return existing;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve an existing publication job through deletion

If Delete is selected while a save/activation job is pending or its reply was lost, current.deleted makes this condition skip the durable existing job; the method then overwrites the publication row with the delete record below. Consequently PromptShortcutRuntime.flush() never sees the obsolete save job and never calls settle(), losing the only identity capable of fencing a staged or already-active body and potentially leaving the supposedly deleted publication or its quota reservation behind. Preserve and settle the existing job before replacing it with deletion.

AGENTS.md reference: packages/shared/src/prompt-shortcuts/AGENTS.md:L36-L37

Useful? React with 👍 / 👎.

Remove the superseded design prototype, unused editable annotations and replacement API, test-only composer compiler and publication helper. Keep real component stories and move stale/duplicate invocation assertions onto the actual send path. Consolidate repeated documentation and preserve locale ordering.

Ablations retain semantic Undo and stale-preparation fences: negative controls fail when either protection is removed. Full workspace typecheck and test:ci pass; installed-workspace lint, formatting, docs, i18n and boundary checks pass.

Model: gpt-6

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a4e4e11477

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

<StuckConnectionBannerContainer />
{workspaceReady ? <DesktopSettingsModal /> : null}
</WorkspaceRuntimeShell>
<PromptShortcutProvider enabled={workspaceReady}>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Gate the Shortcut runtime on the workspace window owner

When Prompt Shortcuts are enabled in Electron, every primary or auxiliary window mounts this provider even though owner already identifies the single workspace window permitted to run singleton background work. Opening a second window for the same workspace therefore creates another PromptShortcutRuntime over the same account/workspace IndexedDB and lets both instances drain the same publication outbox, causing competing ledger writes and duplicate or conflicting cloud publication attempts. Mount the runtime only for the workspace owner or provide a genuinely shared single owner.

AGENTS.md reference: packages/components/src/providers/AGENTS.md:L41-L47

Useful? React with 👍 / 👎.

Comment on lines +53 to +55
getCandidates: (term, limit) =>
selectPromptShortcutCandidates({ entries, context, loading }, term, t, limit).map(
(candidate) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Wire live dependency resolution into Shortcut discovery

For every Shortcut containing a file, Skill, Role, issue, or PR, this production call omits resolveDependency, so selectPromptShortcutCandidates uses unverifiedShortcutDependency and always marks the entry unknown; non-exact matches disappear and exact matches are disabled. The selection, status, and compilation paths likewise never provide a resolver, so users can author reference-bearing Shortcuts but can never insert or send them even when all dependencies are available. Supply the live dependency resolver throughout this composer path.

AGENTS.md reference: packages/components/src/components/mentions/AGENTS.md:L114-L116

Useful? React with 👍 / 👎.

…edium]

Remove dedicated Shortcut suites, stories and feature-only additions to shared fixtures. Retain existing general composer and mention tests, and document the temporary coverage scope without changing production behavior.

Model: gpt-6

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3aca38b3f9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +307 to +308
if (trigger === '/') {
const directCategories = categories.filter((category) => category.directTrigger === '/');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Hide ACP commands from inline slash menus

When Prompt Shortcuts are enabled and the composer already contains ordinary text, / remains active for inline Shortcut insertion, but this branch also includes every ACP command category. Selecting one then replaces only the slash-to-caret query, producing text such as explain this /review; the agent receives an ordinary message instead of the advertised whole-prompt command. Filter ACP commands out whenever the slash trigger is not the entire prompt.

AGENTS.md reference: packages/components/src/components/mentions/AGENTS.md:L117-L118

Useful? React with 👍 / 👎.

Comment on lines +4 to +5
export function promptShortcutDatabaseName(workspaceId: string, userId: string): string {
return `${PROMPT_SHORTCUT_DATA_PREFIX}${encodeURIComponent(workspaceId)}:${encodeURIComponent(userId)}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Register Shortcut databases for hard-reset fallback

On engines where indexedDB.databases() is unavailable or throws, a crash-screen hard reset cannot discover this new account/workspace-specific database name. clearAllLodyLocalData() only falls back to static known names, and the later RuntimeProvider extras contain only the workspace repo and cursor databases, so saved Prompt bodies and outbox data survive the promised full wipe/sign-out. Record these dynamic database names for the hard-reset fallback or pass them explicitly before identity storage is cleared.

AGENTS.md reference: packages/components/src/lib/AGENTS.md:L34-L37

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9cc11cc4ff

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +253 to +260
useEffect(() => {
if (!runtime) return undefined;
const retry = () => {
void runtime.flush();
if (directory) void runtime.setDirectory(directory);
};
window.addEventListener('online', retry);
return () => window.removeEventListener('online', retry);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Schedule retries after failed publication

When a stage, activation, or index-sync request fails while the browser remains online (for example, a transient 5xx), PromptShortcutRuntime.flush() records the error and stops after that one attempt, while this provider retries only on a future online event. Since the settings surface no longer exposes the runtime retry callback, the locally successful save can remain unpublished indefinitely until the user reloads, toggles connectivity, or performs another save. Add a bounded/backoff retry path for failed outbox records rather than relying exclusively on offline-to-online transitions.

Useful? React with 👍 / 👎.

Comment on lines +318 to +320
const siblings = this.list().filter(
(row) =>
!row.deleted && row.entry.id !== value.id && row.entry.visibility === value.visibility

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enforce catalog limits across visibility domains

When an author already has a Shortcut under the other visibility, this predicate excludes it from both slug uniqueness and item/byte quota checks. The local save therefore succeeds for duplicate slugs or a catalog exceeding the cloud publication contract, closes the editor, and only the later background activation rejects it; with publication errors hidden, the entry appears normal locally but never becomes available to its intended audience. Count all non-deleted authored Shortcuts here, regardless of whether their index is private or workspace-visible.

Useful? React with 👍 / 👎.

Remove invocation chips, dedicated draft checkpoints and send compilation. Preserve cancellable selection and ordinary mention ranges.

Model: gpt-6

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 95dfd48568

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

};

export type CloudApi = {
promptShortcuts: {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the required Spec and Agent Note

This introduces a public cloud protocol and new durable persistence, publication, access, and deletion guarantees, but the changed-file list contains neither an owning draft Spec nor an Agent Note. Without those records, the intended cross-client and cloud contracts are not reviewable or traceable; add both in this change as required by the repository’s governance rules.

AGENTS.md reference: AGENTS.md:L15-L21

Useful? React with 👍 / 👎.

@Leeeon233
Leeeon233 merged commit 0b7ef6e into main Sep 11, 2026
6 checks passed
@Leeeon233
Leeeon233 deleted the feat/prompt-shortcut-settings-sync branch September 11, 2026 23:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant